<div id="app">
    
</div>
<script>
    const createAppAPI = (render) => {
        return function createApp(rootComponent){
            const app = {
                mount(rootContainer) {
                    // mount vnode -> dom
                    const vnode = {
                        tag: rootComponent
                    }

                    // to render
                    render(vnode, rootContainer)
                }
            }
            return app
        }
    }

    // 2 render
    const createRenderer = options => {
        const patch = (n1, n2, container) => {
            const rootComponent = n2.tag
            const ctx = {...rootComponent.data()}
            const vnode = rootComponent.render.call(ctx)
            const parent = options.querySelector(container)

            const child = options.createElement(vnode.tag)
            if (typeof vnode.children === 'string') {
                child.textContent = vnode.children
            } else {
                // for array condition
            }
            options.insert(child, parent)
        }
        const render = (vnode, container) => {
            patch(container._vnode || null, vnode, container)
            container._vnode = vnode
        }

        return {
            render,
            createApp: createAppAPI(render)
        }
        
    }

    const renderer = createRenderer({
        querySelector(sel) {
            return document.querySelector(sel)
        },
        createElement(tag) {
            return document.createElement(tag)
        },
        insert(child, parent) {
            parent.appendChild(child)
        }
    })
    // 1. define vue instance
    const Vue = {
        createApp(options) {
            return renderer.createApp(options)
        }
    }

    // simulate vue3 
    Vue.createApp({
        data() {
            return {
                foo: "暗号：mua"
            }
        },
        render() {
            return {
                tag: 'h2',
                children: this.foo
            }
        }
    }).mount('#app')
</script>